#include <iostream>
#include <atomic>
#include <thread>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <unistd.h>
#include <tbb/spin_rw_mutex.h>

class RobustMutex
{
public:
    void Init()
    {
        uint32_t count = m_count.fetch_add(1, std::memory_order_relaxed);
        if (0 == count)
        {
            pthread_mutexattr_init(&m_attr);
            pthread_mutexattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED); // 允许跨进程共享
            pthread_mutexattr_setrobust(&m_attr, PTHREAD_MUTEX_ROBUST);    // 设置为鲁棒互斥锁
            if (pthread_mutex_init(&m_mutex, &m_attr) != 0)
            {
                throw std::runtime_error("Failed to initialize robust mutex");
            }
        }
    }

    void DeInit()
    {
        unlock();
        uint32_t count = m_count.fetch_sub(1, std::memory_order_relaxed);
        if (1 == count)
        {
            pthread_mutex_destroy(&m_mutex);
            pthread_mutexattr_destroy(&m_attr);
        }
    }

    void lock()
    {
        int rc = pthread_mutex_lock(&m_mutex);
        if (rc == EOWNERDEAD)
        {
            pthread_mutex_consistent(&m_mutex);
        }
        else if (rc != 0)
        {
            throw std::runtime_error("Failed to lock mutex");
        }
    }

    void unlock()
    {
        pthread_mutex_unlock(&m_mutex);
    }

    RobustMutex(const RobustMutex &) = delete;
    RobustMutex &operator=(const RobustMutex &) = delete;

private:
    std::atomic<uint32_t> m_count;
    pthread_mutex_t m_mutex;
    pthread_mutexattr_t m_attr;
};

template <typename T>
class ShareMemory
{
public:
    ShareMemory(int key) : m_key(key)
    {
        m_shmID = shmget(m_key, sizeof(Data), 0666 | IPC_CREAT);
        if (m_shmID < 0)
        {
            throw std::runtime_error("shmget failed.");
        }

        m_data = (Data *)shmat(m_shmID, 0, 0);
        if (((void *)(-1)) == (void *)m_data)
        {
            // 映射失败
            std::cerr << "shmat failed: " << errno << std::endl;
            perror("shmat ");
            throw std::runtime_error("shmat failed.");
        }
        int count = m_data->count.fetch_add(1, std::memory_order_relaxed);

        std::cout << "ShareMemory 2, count:" << count << std::endl;

        m_data->data.Init();
    }

    ~ShareMemory()
    {
        m_data->data.DeInit();

        std::cout << "~ShareMemory 1" << std::endl;
        int count = m_data->count.fetch_sub(1, std::memory_order_relaxed);
        if (0 != shmdt(m_data))
        {
            std::cerr << "shmdt failed: " << errno << std::endl;
            perror("shmdt ");
            return;
        }
        std::cout << "~ShareMemory 2, count:" << count << std::endl;
        if (1 == count)
        {
            if (-1 == shmctl(m_shmID, IPC_RMID, NULL))
            {
                // 删除失败
                std::cerr << "shmctl failed: " << errno << std::endl;
                perror("shmctl ");
                return;
            }
        }
    }

    T &Get()
    {
        return m_data->data;
    }

private:
    struct Data
    {
        std::atomic<uint32_t> count;
        T data;
    };

    Data *m_data = nullptr;
    int m_key;
    int m_shmID;
};

struct TestData
{
    void Init()
    {
        m_mutex.Init();
    }

    void DeInit()
    {
        m_mutex.DeInit();
    }

    RobustMutex m_mutex;
    int m_procCount;
    int m_count;
};

struct TestData2
{
    void Init()
    {
        // m_mutex.Init();
    }

    void DeInit()
    {
        // m_mutex.DeInit();
    }
    tbb::detail::d1::spin_rw_mutex m_mutex;
    int m_procCount;
    int m_count;
};